/**
 * File  : Queue.h
 * Time  : 2014-12-19 14:35
 * Author: KashingLee
 * Ref   : Null
 */
#ifndef PLCC_EVENT_QUEUE_QUEUE_H_
#define PLCC_EVENT_QUEUE_QUEUE_H_
#include <stdint.h>

template<class Element>
class Type {
 public:
  Type() :next_(0) {}
  Type(const Element &opcode) :next_(0), opcode_(opcode) {}
  //~Type();

 public:
  void     set_next(Type *next) {next_ = next;}
  void     set_opcode(const Element &opcode) { opcode_ = opcode; }
  Type*    next() const { return next_; }
  Element opcode() const { return opcode_; }
  
 private:
  Type     *next_;
  Element opcode_; 
};

template <class Element>
class Queue {
 public:
  Queue();
  ~Queue();

 public:
  void  EnQueue(const Element&);
  Type<Element>* DeQueue();
  bool  IsEmpty();

 private:
  Type<Element>  *head_;
  Type<Element>  *tail_;
};

template<class Element>
Queue<Element>::Queue() {
  head_ = tail_ = new Type<Element>;
}

template<class Element>
Queue<Element>::~Queue() {
  while (!IsEmpty()) {
    Type<Element> *tmp = DeQueue();
    delete tmp;
  }
  delete head_;
}

template<class Element>
void Queue<Element>::EnQueue(const Element &t) {
  tail_->set_next(new Type<Element>(t));
  tail_ = tail_->next();
}

template<class Element>
Type<Element>* Queue<Element>::DeQueue() {
  Type<Element> *tmp = head_->next();
  head_->set_next(tmp->next());
  if (tmp == tail_) {
    tail_ = head_;
  }
  return tmp;
}

template<class Element>
bool Queue<Element>::IsEmpty() {
  return head_ == tail_;
}
#endif // PLCC_EVENT_QUEUE_QUEUE_H_
